/*
 * VS1003.c
 *
 * Created: 2012-06-09 18:38:01
 *  Author: Sebastian_2
 */ 

#include "../Globals.h"
#include "VS1003.h"
#include "SD/ff.h"
#include "XMEGA.h"
#include <string.h>

#ifndef ATMEGA

void VS1003_Init() {
	VS1003_DCS_PORT.DIRSET = VS1003_DCS_bm;
	VS1003_CS_PORT.DIRSET = VS1003_CS_bm;
	VS1003_DREQ_PORT.DIRCLR = VS1003_DREQ_bm;
	VS1003_DREQ_PORT.PIN1CTRL = PORT_OPC_TOTEM_gc | PORT_ISC_RISING_gc | PORT_INT0LVL_HI_gc;
	VS1003_DREQ_PORT.INT0MASK = VS1003_DREQ_bm;
	EVSYS.CH0MUX = EVSYS_CHMUX_PORTE_PIN1_gc;
	
	DMA.CTRL = DMA_ENABLE_bm | DMA_DBUFMODE_CH01_gc; // double buffer on CH0 and CH1
	DMA.CH0.CTRLA = DMA_CH_ENABLE_bm | DMA_CH_REPEAT_bm | DMA_CH_BURSTLEN_4BYTE_gc;
	DMA.CH0.CTRLB = DMA_CH_TRNINTLVL_HI_gc;
	DMA.CH0.ADDRCTRL = DMA_CH_SRCRELOAD_TRANSACTION_gc | DMA_CH_SRCDIR_INC_gc | DMA_CH_DESTRELOAD_NONE_gc | DMA_CH_DESTDIR_FIXED_gc;
	DMA.CH0.TRIGSRC = DMA_CH_TRIGSRC_EVSYS_CH0_gc;
	DMA.CH0.TRFCNT = 32;
	DMA.CH0.REPCNT = VS1003_BUFSIZE/32;
	DMA.CH0.SRCADDR0 = (((uint16_t)&gVS1003Buffer1)>>0) & 0xFF;
	DMA.CH0.SRCADDR1 = (((uint16_t)&gVS1003Buffer1)>>8) & 0xFF; 
	DMA.CH0.SRCADDR2 = 0;//(((uint16_t)&gVS1003Buffer1)>>16) & 0xFF; 
	DMA.CH0.DESTADDR0 = (((uint16_t)&(VS1003_USART.DATA))>>0*8) & 0xFF;
	DMA.CH0.DESTADDR1 = (((uint16_t)&(VS1003_USART.DATA))>>1*8) & 0xFF;
	DMA.CH0.DESTADDR2 = 0;//(((uint16_t)&(VS1003_USART.DATA))>>2*8) & 0xFF;
	
	DMA.CH1.CTRLA = DMA_CH_ENABLE_bm | DMA_CH_REPEAT_bm | DMA_CH_BURSTLEN_4BYTE_gc;
	DMA.CH1.CTRLB = DMA_CH_TRNINTLVL_HI_gc;
	DMA.CH1.ADDRCTRL = DMA_CH_SRCRELOAD_TRANSACTION_gc | DMA_CH_SRCDIR_INC_gc | DMA_CH_DESTRELOAD_NONE_gc | DMA_CH_DESTDIR_FIXED_gc;
	DMA.CH1.TRIGSRC = DMA_CH_TRIGSRC_EVSYS_CH0_gc;
	DMA.CH1.TRFCNT = 32;
	DMA.CH1.REPCNT = VS1003_BUFSIZE/32;
	DMA.CH1.SRCADDR0 = (((uint16_t)&gVS1003Buffer2)>>0*8) & 0xFF;
	DMA.CH1.SRCADDR1 = (((uint16_t)&gVS1003Buffer2)>>1*8) & 0xFF; 
	DMA.CH1.SRCADDR2 = 0;//(((uint16_t)&gVS1003Buffer2)>>2*8) & 0xFF; 
	DMA.CH1.DESTADDR0 = (((uint16_t)&(VS1003_USART.DATA))>>0*8) & 0xFF;
	DMA.CH1.DESTADDR1 = (((uint16_t)&(VS1003_USART.DATA))>>1*8) & 0xFF;
	DMA.CH1.DESTADDR2 = 0;//(((uint16_t)&(VS1003_USART.DATA))>>2*8) & 0xFF;
	
	USART_SPI_Init(&VS1003_USART, VS1003_BAUD);
}

void VS1003_SoftReset() {
	DMA.CH0.CTRLA &= ~DMA_CH_ENABLE_bm; // abort current transaction
	DMA.CH1.CTRLA &= ~DMA_CH_ENABLE_bm;
	
	VS1003_CS_CLR();
	while(bit_is_set(VS1003_DREQ_PORT.IN, VS1003_DREQ_bm)); // go on if DREQ is high
	USART_SPI_Write(&VS1003_USART, WRITE);
	while(bit_is_set(VS1003_DREQ_PORT.IN, VS1003_DREQ_bm)); // go on if DREQ is high
	USART_SPI_Write(&VS1003_USART, MODE_ADDR);
	while(bit_is_set(VS1003_DREQ_PORT.IN, VS1003_DREQ_bm)); // go on if DREQ is high
	USART_SPI_Write(&VS1003_USART, MODE_RESET >> 8);
	while(bit_is_set(VS1003_DREQ_PORT.IN, VS1003_DREQ_bm)); // go on if DREQ is high
	USART_SPI_Write(&VS1003_USART, (uint8_t)MODE_RESET);
	while(bit_is_set(VS1003_DREQ_PORT.IN, VS1003_DREQ_bm)); // go on if DREQ is high
	VS1003_CS_SET();
	
	// soft reset is done
	DMA.CH0.CTRLA |= DMA_CH_ENABLE_bm;
	DMA.CH1.CTRLA |= DMA_CH_ENABLE_bm;
}

void VS1003_PlayFile(uint8_t playlistID, uint8_t songID) {
	VS1003_SoftReset();
	
	FRESULT res;
	uint16_t bytesRead;
	char s[50];
	
	// first off read playlist file
	
	res = f_open(&gVS1003File, "/pls/index", FA_OPEN_EXISTING | FA_READ);
	if(!res) return;
	
	char *s_ptr;
	for(uint16_t i = 0; i < playlistID+1; i++) { // go through playlist index to find correct playlist
		s_ptr = f_gets(s, sizeof(s), &gVS1003File);
		//if(*s_ptr != s) return;
	}
	
	
	
	// once we have playlist entry
	
	res = f_open(&gVS1003File, s, FA_OPEN_EXISTING);
	if(!res) return;
	
	// first off read playlist file
	
	
	f_read(&gVS1003File, &gVS1003Buffer1, VS1003_BUFSIZE, &bytesRead);
	
	//VS1003_ReadTags();
	
	f_read(&gVS1003File, &gVS1003Buffer2, VS1003_BUFSIZE, &bytesRead);
	
	DMA.CH0.CTRLA |= DMA_CH_TRFREQ_bm; // start DMA transaction
}

#endif